package com.me.study.jdk8.optional;

import org.junit.Before;
import org.junit.Test;
import spring.validation.Person;

import java.util.NoSuchElementException;
import java.util.Optional;

import static org.junit.Assert.*;

/**
 * JDK1.8 新特性：Optional<T> 优雅的判断 null
 *
 * @author ME
 * @date   2019/12/24
 */
public class TestOptional {
    private Person person = null;
    private Optional<Person> personOpt;
    private Optional<Person> optNull;

    @Before
    public void before() {
        person = new Person("ljy", "27");
        // 构建一个可为空的 Optional
        personOpt = Optional.ofNullable(person);
        optNull = Optional.ofNullable(null);
    }

    @Test(expected = NullPointerException.class)
    public void of() {
        // 允许为空
        Optional.ofNullable(null);
        // 不允许为空
        Optional.of(null);
        fail("of() 入参不能为空");
    }

    @Test(expected = NoSuchElementException.class)
    public void get() {
        // if (person != null) {
        //     return person;
        // } else {
        //     throw new RuntimeException();
        // }

        assertEquals("元素存在则返回",
                person, personOpt.get());
        System.out.println(optNull.get());
        fail("元素不存在异常，抛异常 NoSuchElementException");
    }

    @Test
    public void orElse() {
        // if (person != null) {
        //     return person;
        // } else {
        //     // return null;
        //     return new Person("Tom", "11");
        // }

        final Person tom = new Person("Tom", "11");
        assertEquals("存在则返回，不存在则返回 提供的默认值：",
                tom, optNull.orElse(tom));
    }

    @Test
    public void orElseGet() {
        // if (person != null) {
        //     return person;
        // } else {
        //     return new Person("Jack", "13");
        // }

        final Person jack = new Person("Jack", "13");
        assertEquals("存在则返回，不存在则 由函数产生：",
                jack, optNull.orElseGet(() -> jack));
    }

    @Test(expected = RuntimeException.class)
    public void orElseThrow() {
        final RuntimeException exception = new RuntimeException("存在则返回，不存在则 抛异常");
        optNull.orElseThrow(() -> exception);
        fail("不抛异常是不对的");
    }

    @Test
    public void ifPresent() {
        System.out.println("非空就开始搞事情：" + person);
        // if (person != null) {
        //     System.out.println(person);
        // }

        personOpt.ifPresent(System.out::println);
    }

    @Test
    public void map() {
        // System.out.println(personOpt.map(p -> p.getDisplayName()).map(name -> name.toUpperCase()).orElse(null));
        // 简写：
        assertEquals("可为空的值转换",
                "LJY", personOpt.map(Person::getName).map(String::toUpperCase).get());
        assertNull("可为空的值转换",
                personOpt.map(Person::getTime).map(String::toUpperCase).orElse(null));
    }

    @Test
    public void flatMap() {
        assertEquals("自定义Optional 并进行值转换",
                "LJY", personOpt.flatMap(person1 -> Optional.of(person1.getName()))
                        .map(String::toUpperCase).get());
        assertNull("自定义Optional 并进行值转换",
                personOpt.flatMap(person1 -> Optional.ofNullable(person1.getTime()))
                        .map(String::toUpperCase).orElse(null));
    }

}
